延續昨天補位的情境,我們今天要來實作一下補位的範例,同樣以官方提供的範例碼,由筆者加上註解與 debuf log 編譯完成後,放到 docker hub 上提供大家體驗看看,請使用這份 backfill.yaml 部署,裏面使用的是註解過後的 MMF。
同基本範例兩人成團的情境,本次若在第一時間不足兩人時,會產生一個補位的 backfill

這部分跟原本不同的地方在於,除了呼叫 matchfunction.QueryPool 以外, 還需要確認補問的部分,因此需要額外呼叫 matchfunction.QueryBackfillPool ,來帶入我們的配對邏輯 makeMatches 中。
func (s *matchFunctionService) Run(req *pb.RunRequest, stream pb.MatchFunction_RunServer) error {
	log.Printf("Generating proposals for function %v", req.GetProfile().GetName())
	var proposals []*pb.Match
	profile := req.GetProfile()
	pools := profile.GetPools()
	for _, p := range pools {
		tickets, err := matchfunction.QueryPool(stream.Context(), s.queryServiceClient, p)
		if err != nil {
			log.Printf("Failed to query tickets for the given pool, got %s", err.Error())
			return err
		}
		backfills, err := matchfunction.QueryBackfillPool(stream.Context(), s.queryServiceClient, p)
		if err != nil {
			log.Printf("Failed to query backfills for the given pool, got %s", err.Error())
			return err
		}
		for i := range backfills {
			log.Printf("QueryBackfillPool get backfill_id: %s\n", backfills[i].Id)
		}
		matches, err := makeMatches(profile, p, tickets, backfills)
		if err != nil {
			log.Printf("Failed to generate matches, got %s", err.Error())
			return err
		}
		proposals = append(proposals, matches...)
	}
	log.Printf("Streaming %v proposals to Open Match", len(proposals))
	// Stream the generated proposals back to Open Match.
	for _, proposal := range proposals {
		if err := stream.Send(&pb.RunResponse{Proposal: proposal}); err != nil {
			log.Printf("Failed to stream proposals to Open Match, got %s", err.Error())
			return err
		}
	}
	return nil
}
這裡是我們實踐補位邏輯的核心,在拿到想要配對的 tickets 與需要補位的數量 backfills 後,我們可以依據我們的配對人數,先將補位的部分處理好,如果補位後還有 tickets 則先配對成新遊戲,若有不足人數時(餘數),則在給予新的 backfill 。
func makeMatches(profile *pb.MatchProfile, pool *pb.Pool, tickets []*pb.Ticket, backfills []*pb.Backfill) ([]*pb.Match, error) {
	var matches []*pb.Match
	//先將 backfills 裡面的空位填滿
	newMatches, remainingTickets, err := handleBackfills(profile, tickets, backfills, len(matches))
	if err != nil {
		return nil, err
	}
	//持續依照遊戲上線湊滿房間 create normal match
	matches = append(matches, newMatches...)
	newMatches, remainingTickets = makeFullMatches(profile, remainingTickets, len(matches))
	matches = append(matches, newMatches...)
	//餘數沒滿的情況 create match with backfill
	if len(remainingTickets) > 0 {
		match, err := makeMatchWithBackfill(profile, pool, remainingTickets, len(matches))
		if err != nil {
			return nil, err
		}
		matches = append(matches, match)
	}
	return matches, nil
}
可以透過在 MMF 加入的 debug log,來協助我們觀察其補位的過程